<?php
// +----------------------------------------------------------------------
// | [ WE ONLY DO WHAT IS NECESSARY ]
// +----------------------------------------------------------------------
// | Author < 931274989@qq.com >
// +----------------------------------------------------------------------
// | Explain 
// +----------------------------------------------------------------------
namespace app\api\service;

use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use app\model\User as UserModel;
use app\lib\enum\ScopeEnum;
use think\Exception;

class UserToken extends Token
{
  protected $code;
  protected $wxAppID;
  protected $wxAppSecret;
  protected $wxLoginUrl;

  function __construct($code)
  {
    $this->code = $code;
    $this->wxAppID = config('wx.app_id');
    $this->wxAppSecret = config('wx.app_secret');
    $this->wxLoginUrl = sprintf(
      config('wx.login_url'),$this->wxAppID,$this->wxAppSecret,$this->code);

  }

  // 获取微信session_key及openID
  public function get()
  {
    $result = curl_get($this->wxLoginUrl);
    $wxResult = json_decode($result, true);
    if (empty($wxResult)) {
      throw new Exception('获取session_key及openID时异常，微信内部错误');
    }
    else {
      $loginFail = array_key_exists('errcode',$wxResult);
      if($loginFail) {
        $this->processLoginError($wxResult);
      }
      else {
        return $this->grantToken($wxResult);
      }
    }
  }

  private function grantToken($wxResult)
  {
    // 拿到openid
    // 查看数据库 openid是否存在
    // 如果存在不处理、不存在则添加一条user记录
    // 生成令牌，准备缓存数据、写入缓存
    // 把令牌返回到客户端
    // key：令牌
    // value：wxResult, uid, scope
    $openid = $wxResult['openid'];
    $user = UserModel::getByOpenID($openid);
    if ($user) {
      $uid = $user->id;
    }
    else {
      $uid = $this->newUser($openid);
    }
    $cachedValue = $this->prepareCachedValue($wxResult,$uid);
    $token = $this->saveToCache($cachedValue);
    return $token;
  }

  // 写入缓存
  private function saveToCache($cachedValue)
  {
    $key = self::generateToken();
    $value = json_encode($cachedValue);
    $expire_in = config('setting.token_expire_in');
    $request = cache($key, $value, $expire_in);
    if (!$request) {
      throw new TokenException([
        'msg' => '服务器缓存异常',
        'errorCode' => 10005,
      ]);
    }
    return $key;
  }

  // 准备缓存数据
  private function prepareCachedValue($wxResult,$uid)
  {
    $cachedValue = $wxResult;
    $cachedValue['uid'] = $uid;
    // 用户权限
    $cachedValue['scope'] = ScopeEnum::User;
    return $cachedValue;
  }

  // 添加新用户
  private function newUser($openid)
  {
    $user = UserModel::create(['openid' => $openid]);
    return $user->id;
  }

  // 微信获取session_key及openID异常处理
  private function processLoginError($wxResult){
    throw new WeChatException([
      'msg' => $wxResult['errmsg'],
      'errorCode' => $wxResult['errcode']
    ]);
  }
  
}
?>